/**
 * @param {number[]} nums
 * @param {number} target
 * @return {number}
 */
var threeSumClosest = function (nums, target) {
  // 先排序，少执行一部分比较
  nums.sort((a, b) => {
    return a - b;
  });
  let n = nums.length,
    minSum;
  for (let i = 0; i < n - 2; i++) {
    if (i > 1 && nums[i] === nums[i - 1]) continue;
    let j = i + 1,
      m = n - 1;
    while (j < m) {
      let he = nums[i] + nums[j] + nums[m];
      if (he === target) return he;
      minSum = minSum === undefined ? he : Math.abs(target - minSum) > Math.abs(target - he) ? he : minSum;
      //   如果和比target大，右指针左移，同时去掉相同值
      if (he > target) {
        let m0 = m;
        while (j < m0 - 1 && nums[m0] === nums[m0 - 1]) {
          m0--;
        }
        m = --m0;
      } else {
        //   如果和比target小，左指针右移，同时去掉相同值
        // 不能因为找到一个比target小的值，就认为其余的值都比target更小了
        let j0 = j;
        while (j < m - 1 && nums[j0] === nums[j0 + 1]) {
          j0++;
        }
        j = ++j0;
      }
    }
  }
  return minSum;
};
